//
//  NSString+JJ.m
//  JJObjCTool
//
//  Created by hamilyjing on 5/11/15.
//  Copyright (c) 2015 gongjian. All rights reserved.
//

#import "NSString+JJ.h"

#import <CommonCrypto/CommonDigest.h>

@implementation NSString (JJ)

#pragma mark - mask code

+ (NSString *)maskCode:(NSString *)name {
    NSString *mask = name;
    if (name.length && ![name isEqualToString:@"null"]) {
        if (name.length == 2){
            mask = [NSString stringWithFormat:@"%@*", [name substringToIndex:1]];
        }
        if(name.length>2 && name.length<7){
            NSMutableString * mustr = [name mutableCopy];
            NSString * starString = @"";
            for (int i = 0; i<mustr.length-2; i++) {
                starString = [starString stringByAppendingString:@"*"];
            }
            [mustr replaceCharactersInRange:NSMakeRange(1, mustr.length-2) withString:starString];
            mask = mustr;
        }
        if(name.length >= 7 && name.length <= 9){
            NSMutableString *mustr = [name mutableCopy];
            NSString * starString = @"";
            for (int i = 0; i < mustr.length-4; i++) {
                starString = [starString stringByAppendingString:@"*"];
            }
            [mustr replaceCharactersInRange:NSMakeRange(2, mustr.length-4) withString:starString];
            mask = mustr;
        }
        if(name.length>9){
            NSMutableString * mustr = [name mutableCopy];
            NSString * starString = @"";
            for (int i = 0; i<mustr.length-6; i++) {
                starString = [starString stringByAppendingString:@"*"];
            }
            [mustr replaceCharactersInRange:NSMakeRange(3, mustr.length-6) withString:starString];
            mask = mustr;
        }
    }
    return mask;
}

#pragma mark - Data

- (NSData *)jj_data
{
    return [self dataUsingEncoding:NSUTF8StringEncoding];
}

#pragma mark - UI

- (CGSize)jj_textSize:(UIFont *)font
{
    if ([self length] <= 0)
    {
        return CGSizeZero;
    }
    
    CGSize size;
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000
    size = [self sizeWithAttributes:@{NSFontAttributeName:font}];
#else
    size = [self sizeWithFont:font];
#endif
    
    return size;
}

#pragma mark - Remove characters

- (NSString *)jj_trimWhitespace
{
    return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}

- (NSString *)jj_trimNewline;
{
    return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}

- (NSString *)jj_trimWhitespaceAndNewline;
{
    return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}

#pragma mark - UUID

+ (NSString *)jj_UUID
{
    CFUUIDRef uuidRef = CFUUIDCreate(NULL);
    CFStringRef uuid = CFUUIDCreateString(NULL, uuidRef);
    
    CFRelease(uuidRef);
    
    return (__bridge_transfer NSString *)uuid;
}

#pragma mark - MD5

- (NSString *)jj_md5String
{
    const char *cStr = [self UTF8String];
    unsigned char result[16];
    CC_MD5(cStr, (unsigned int) strlen(cStr), result);
    NSString *md5String = [NSString stringWithFormat:
            @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
            result[0], result[1], result[2], result[3],
            result[4], result[5], result[6], result[7],
            result[8], result[9], result[10], result[11],
            result[12], result[13], result[14], result[15]
            ];
    return md5String;
}

- (NSData *)jj_md5Data
{
    return [[self jj_md5String] jj_data];
}

#pragma mark - Base64

- (NSString *)jj_base64EncodedString
{
#pragma warning - parameter right?
    NSString *base64EncodedString = [[self jj_data] base64EncodedStringWithOptions:0];
    return base64EncodedString;
}

- (NSData *)jj_base64EncodedData
{
    NSData *base64EncodedData = [[self jj_data] base64EncodedDataWithOptions:0];
    return base64EncodedData;
}

- (NSString *)jj_base64DecodedString
{
    NSString *base64DecodedString = [[NSString alloc] initWithData:[self jj_base64DecodedData] encoding:NSUTF8StringEncoding];
    return base64DecodedString;
}

- (NSData *)jj_base64DecodedData
{
    NSData *base64DecodedData = [[NSData alloc] initWithBase64EncodedData:[self jj_data] options:0];
    return base64DecodedData;
}

#pragma mark - JSON

- (NSDictionary *)jj_dictionaryWithJSON
{
    NSData *data = [self jj_data];
    if (!data)
    {
        return nil;
    }
    
    NSError *error;
    id result = [NSJSONSerialization JSONObjectWithData:data
                                                options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves
                                                  error:&error];
    
    if (error)
    {
        //会造成崩溃
        //NSAssert(NO, @"From data to JSON object error: %@", error);
    }
    
    return result;
}

+ (id)jj_convertToStrictDictionaryWithJSONStringWithOtherInfo:(id)otherInfo {
    return [NSString jj_convertToStrictDictionaryWithJSONStringWithOtherInfo:otherInfo callback:nil];
}

+ (id)jj_convertToStrictDictionaryWithJSONStringWithOtherInfo:(id)otherInfo callback:(void (^)(NSDictionary *, id))callback{
    
    NSString *data = nil;
    if ([otherInfo isKindOfClass:[NSDictionary class]]) {
        data = [(NSDictionary *)otherInfo objectForKey:@"responseString"];
    }
    
    NSDictionary *responseDict = nil;
    id bodyDict = nil;
    if ([data isKindOfClass:[NSString class]]) {
        responseDict = [(NSString *)data jj_dictionaryWithJSON];
        
        if ([responseDict isKindOfClass:[NSDictionary class]]) {
            bodyDict = responseDict[@"body"];
        }else {
            responseDict = nil;
        }
    }
    
    if (callback) {
        callback(responseDict,bodyDict);
    }
    
    return bodyDict;
}

+ (NSString *)jj_stringByRemovingCharactersInSet:(NSCharacterSet*) charsToRemove withString:(NSString *)str
{
    NSString* result;
    int index;
    int outputCount = 0;
    unichar aChar;
    NSUInteger charCount = [str length];
    unichar* outputChars = malloc(charCount * sizeof(unichar));
    for (index = 0; index < charCount; index++)
    {
        aChar = [str characterAtIndex: index];
        if (![charsToRemove characterIsMember: aChar])
            outputChars[outputCount++] = aChar;
    }
    result = [NSString stringWithCharacters: outputChars length: outputCount];
    free (outputChars);
    return result;
}

#pragma mark - URL

- (NSString*)jj_urlEncodedString
{
    return [self jj_urlEncodeUsingEncoding:kCFStringEncodingUTF8];
}

- (NSString*)jj_urlDecodedString
{
    return [self jj_urlDecodeUsingEncoding:kCFStringEncodingUTF8];
}

- (NSString *)jj_urlEncodeUsingEncoding:(CFStringEncoding)encoding
{
    CFStringRef encodedCFString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                          (__bridge CFStringRef) self,
                                                                          nil,
                                                                          CFSTR("?!@#$^&%*+,:;='\"`<>()[]{}/\\| "),
                                                                          encoding);
    
    NSString *encodedString = [[NSString alloc] initWithString:(__bridge_transfer NSString*) encodedCFString];
    
    return encodedString;
}

- (NSString *)jj_urlDecodeUsingEncoding:(CFStringEncoding)encoding
{
    CFStringRef decodedCFString = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault,
                                                                                          (__bridge CFStringRef) self,
                                                                                          CFSTR(""),
                                                                                          encoding);
    
    
    NSString *decodedString = [[NSString alloc] initWithString:(__bridge_transfer NSString*) decodedCFString];
    
    if (decodedString)
    {
        // We need to replace "+" with " " because the CF method above doesn't do it
        decodedString = [decodedString stringByReplacingOccurrencesOfString:@"+" withString:@" "];
    }
    
    return decodedString;
}

- (NSDictionary *)jj_dictionaryWithURLQuery
{
    NSArray * params = [self componentsSeparatedByString:@"&"];
    NSMutableDictionary * ret = [NSMutableDictionary dictionary];
    for (NSString * param in params)
    {
        NSRange range = [param rangeOfString:@"="];
        if (range.location != NSNotFound)
        {
            NSString * key = [param substringToIndex:range.location];
            NSString * value = [param substringFromIndex:range.location + 1];
            [ret setValue:value forKey:key];
        }
    }
    return ret;
}

#pragma mark - SubString

- (BOOL)jj_containsString:(NSString *)string
{
    return [self jj_containsString:string options:0];
}

- (BOOL)jj_containsString:(NSString *)string
                  options:(NSStringCompareOptions)options
{
    NSRange range = [self rangeOfString:string options:options];
    BOOL exist = range.location != NSNotFound;
    return exist;
}

- (NSString *)jj_subStringBeforeFirstSeparator:(NSString *)separator_
{
    NSRange range = [self rangeOfString:separator_];
    if (NSNotFound == range.location)
    {
        return nil;
    }
    
    NSString *str = [self substringToIndex:range.location];
    return str;
}

- (NSString *)jj_subStringAfterFirstSeparator:(NSString *)separator_
{
    NSRange range = [self rangeOfString:separator_];
    if (NSNotFound == range.location)
    {
        return nil;
    }
    
    NSString *str = [self substringFromIndex:range.location + range.length];
    return str;
}

- (NSArray *)jj_stringBetweenTheSameString:(NSString *)separator
{
    NSArray *array = [self componentsSeparatedByString:separator];
    NSMutableArray *resultMArray;
    if ([array count] > 0)
    {
        resultMArray = [NSMutableArray arrayWithArray:array];
        [resultMArray removeObjectAtIndex:0];
        [resultMArray removeLastObject];
    }
    return resultMArray;
}

#pragma mark - remove NSString_extra to here TODO:lynn

+ (NSString *)MD5StringFrom:(NSString*)source{
    if(source == nil || [source length] == 0)
        return nil;
    
    const char *value = [source UTF8String];
    
    unsigned char outputBuffer[CC_MD5_DIGEST_LENGTH];
    CC_MD5(value, (unsigned int)strlen(value), outputBuffer);
    
    NSMutableString *outputString = [[NSMutableString alloc] initWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
    for(NSInteger count = 0; count < CC_MD5_DIGEST_LENGTH; count++){
        [outputString appendFormat:@"%02x",outputBuffer[count]];
    }
    
    return outputString;
    
}

-(NSString *)milliSecondString2Second{
    if (self.length>10) {
        return [NSString stringWithFormat:@"%lld.%lld",  [self longLongValue]/1000,[self longLongValue]%1000];
    }
    return self;
}

- (NSString *)URLEncodedString
{
    NSString *result = (NSString *)
    CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                              (CFStringRef)self,
                                                              NULL,
                                                              CFSTR("!*'();:@&amp;=+$,/?%#[] "),
                                                              kCFStringEncodingUTF8));
    return result;
}

- (NSString*)URLDecodedString
{
    NSString *result = (NSString *)
    CFBridgingRelease(CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault,
                                                                              (CFStringRef)self,
                                                                              CFSTR(""),
                                                                              kCFStringEncodingUTF8));
    return result;
}
+(NSString *) normaPhoneNumber:(NSString *)number
{
    NSMutableString *strippedString = [NSMutableString
                                       stringWithCapacity:number.length];
    
    NSScanner *scanner = [NSScanner scannerWithString:number];
    NSCharacterSet *numbers = [NSCharacterSet
                               characterSetWithCharactersInString:@"0123456789"];
    
    while ([scanner isAtEnd] == NO) {
        NSString *buffer;
        if ([scanner scanCharactersFromSet:numbers intoString:&buffer]) {
            [strippedString appendString:buffer];
        }
        // --------- Add the following to get out of endless loop
        else {
            [scanner setScanLocation:([scanner scanLocation] + 1)];
        }
        // --------- End of addition
    }
    return strippedString;
}
- (NSRange)composedRangeWithRange:(NSRange)range {
    // We're going to make a new range that takes into account surrogate unicode pairs (composed characters)
    __block NSRange adjustedRange = range;
    
    // Adjust the location
    [self enumerateSubstringsInRange:NSMakeRange(0, range.location + 1) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
        // If they string the iterator found is greater than 1 in length, add that to range location.
        // This means that there is a composed character before where the range starts who's length is greater than 1.
        adjustedRange.location += substring.length - 1;
    }];
    
    // Adjust the length
    NSInteger length = self.length;
    // Count how many times we iterate so we only iterate over what we care about.
    __block NSInteger count = 0;
    [self enumerateSubstringsInRange:NSMakeRange(adjustedRange.location, length - adjustedRange.location) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
        // If they string the iterator found is greater than 1 in length, add that to range length.
        // This means that there is a composed character inside of the range starts who's length is greater than 1.
        adjustedRange.length += substring.length - 1;
        
        // Add one to the count
        count++;
        
        // If we have iterated as many times as the original length, stop.
        if (range.length == count) {
            *stop = YES;
        }
    }];
    
    // Make sure we don't make an invalid range. This should never happen, but let's play it safe anyway.
    if (adjustedRange.location + adjustedRange.length > length) {
        adjustedRange.length = length - adjustedRange.location - 1;
    }
    
    // Return the adjusted range
    return adjustedRange;
}
- (NSString *)composedSubstringWithRange:(NSRange)range {
    // Return a substring using a composed range so surrogate unicode pairs (composed characters) count as 1 in the
    // range instead of however many unichars they actually are.
    return [self substringWithRange:[self composedRangeWithRange:range]];
}
- (NSString *)composedStringFromIndex:(int)index{
    NSRange range = NSMakeRange(index, self.length - index);
    return [self substringWithRange:[self composedRangeWithRange:range]];
}
- (NSString *)composedStringToIndex:(int)index{
    NSRange range = NSMakeRange(0, index);
    return [self substringWithRange:[self composedRangeWithRange:range]];
}
+(BOOL)isContainsEmoji:(NSString *)string {
    __block BOOL isEomji = NO;
    [string enumerateSubstringsInRange:NSMakeRange(0,[string length]) options:NSStringEnumerationByComposedCharacterSequences usingBlock:
     ^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
         const unichar hs = [substring characterAtIndex:0];
         // surrogate pair
         if (0xd800 <= hs && hs <= 0xdbff) {
             if (substring.length > 1) {
                 const unichar ls = [substring characterAtIndex:1];
                 const int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
                 if (0x1d000 <= uc && uc <= 0x1f77f) {
                     isEomji = YES;
                 }
             }
         } else if (substring.length > 1) {
             const unichar ls = [substring characterAtIndex:1];
             if (ls == 0x20e3) {
                 isEomji = YES;
             }
         } else {
             // non surrogate
             if (0x2100 <= hs && hs <= 0x27ff && hs != 0x263b) {
                 isEomji = YES;
             } else if (0x2B05 <= hs && hs <= 0x2b07) {
                 isEomji = YES;
             } else if (0x2934 <= hs && hs <= 0x2935) {
                 isEomji = YES;
             } else if (0x3297 <= hs && hs <= 0x3299) {
                 isEomji = YES;
             } else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b || hs == 0x2b50|| hs == 0x231a ) {
                 isEomji = YES;
             }
         }
     }];
    return isEomji;
}
unsigned char strToChar (char a, char b);
unsigned char strToChar (char a, char b)
{
    char encoder[3] = {'\0','\0','\0'};
    encoder[0] = a;
    encoder[1] = b;
    return (char) strtol(encoder,NULL,16);
}
- (NSData*) dataFromHex
{
    /*
     NSMutableData *data = [[NSMutableData alloc] init];
     unsigned char whole_byte;
     char byte_chars[3] = {'\0','\0','\0'};
     int i;
     for (i=0; i < 8; i++) {
     byte_chars[0] = [self characterAtIndex:i*2];
     byte_chars[1] = [self characterAtIndex:i*2+1];
     whole_byte = strtol(byte_chars, NULL, 16);
     [data appendBytes:&whole_byte length:1];
     }
     return data;*/
    
    const char * bytes = [self cStringUsingEncoding: NSUTF8StringEncoding];
    NSUInteger length = strlen(bytes);
    unsigned char * r = (unsigned char *) malloc(length / 2 + 1);
    unsigned char * index = r;
    
    while ((*bytes) && (*(bytes +1))) {
        *index = strToChar(*bytes, *(bytes +1));
        index++;
        bytes+=2;
    }
    *index = '\0';
    
    NSData * result = [NSData dataWithBytes: r length: length / 2];
    free(r);
    
    return result;
}
- (NSString *)stringByReversed
{
    NSMutableString *s = [NSMutableString string];
    for (NSUInteger i=self.length; i>0; i--) {
        [s appendString:[self substringWithRange:NSMakeRange(i-1, 1)]];
    }
    return s;
}

#pragma mark - remove NSString_CMUtils to here TODO:yinxukun

+ (BOOL)jj_isBlank:(NSString *)str
{
    if (!str
        || [str isKindOfClass:[NSNull class]]
        || [str isEqualToString:@""]
        || [[str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] isEqualToString:@""]) {
        return YES;
    } else {
        return NO;
    }
}

+ (BOOL)jj_isEmpty:(NSString *)str
{
    if (!str
        || [str isKindOfClass:[NSNull class]]
        || [str isEqualToString:@""]) {
        return YES;
    } else {
        return NO;
    }
}

+ (NSString *)jj_emptyOrString:(NSString *)str
{
    return [NSString jj_isEmpty:str] ? @"" : str;
}

+ (NSString *)jj_emptyOrStringAndTrim:(NSString *)str
{
    return [NSString jj_isEmpty:str] ? @"" : [str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}

+ (NSString *)jj_defaultValue:(NSString *)defaultStr OrString:(NSString *)str
{
    defaultStr = [NSString jj_isEmpty:defaultStr] ? @"" : defaultStr; // default为nil就赋值为空串
    return [NSString jj_isEmpty:str] ? defaultStr : str;
}

- (NSString *)jj_base64String
{
    NSData *data = [NSData dataWithBytes:[self UTF8String] length:[self lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
    NSUInteger length = [data length];
    NSMutableData *mutableData = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
    
    uint8_t *input = (uint8_t *)[data bytes];
    uint8_t *output = (uint8_t *)[mutableData mutableBytes];
    
    for (NSUInteger i = 0; i < length; i += 3) {
        NSUInteger value = 0;
        for (NSUInteger j = i; j < (i + 3); j++) {
            value <<= 8;
            if (j < length) {
                value |= (0xFF & input[j]);
            }
        }
        
        static uint8_t const kAFBase64EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        
        NSUInteger idx = (i / 3) * 4;
        output[idx + 0] = kAFBase64EncodingTable[(value >> 18) & 0x3F];
        output[idx + 1] = kAFBase64EncodingTable[(value >> 12) & 0x3F];
        output[idx + 2] = (i + 1) < length ? kAFBase64EncodingTable[(value >> 6)  & 0x3F] : '=';
        output[idx + 3] = (i + 2) < length ? kAFBase64EncodingTable[(value >> 0)  & 0x3F] : '=';
    }
    
    NSString *retString = [[NSString alloc] initWithData:mutableData encoding:NSASCIIStringEncoding];
    return retString;
}

- (id)jj_objectFromJSONString {
    NSData* data = [self dataUsingEncoding:NSUTF8StringEncoding];
    __autoreleasing NSError* error = nil;
    id result = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
    if (error != nil) return nil;
    return result;
}

+ (NSString *)jj_noNilString:(NSString *)str {
    if (!str) {
        return @"";
    }
    if ([str isEqualToString:@"<null>"]) {
        return @"";
    }
    if ([str isKindOfClass:[NSNull class]]) {
        return @"";
    }
    if ([str isKindOfClass:[NSNumber class]]) {
        
        return [(NSNumber *)self stringValue];
    }
    return str;
}

// 手机号格式化（3 4 4）
+ (NSString *)jj_phoneNumberFormat:(NSString *)phoneNumber
{
    if (![phoneNumber jj_isPhoneNumber]) {
        return phoneNumber;
    }
    NSString *currentStr = [phoneNumber stringByReplacingOccurrencesOfString:@" " withString:@""];
    
    //转临时可变字符串
    NSMutableString *tempStr = [currentStr mutableCopy];
    
    //计算拥有“-”的个数
    int spaceCount = 0;
    if (currentStr.length < 4 && currentStr.length > -1) {
        spaceCount = 0;
    }else if (currentStr.length < 8 && currentStr.length > 3) {
        spaceCount = 1;
    }else if (currentStr.length < 12 && currentStr.length > 7) {
        spaceCount = 2;
    }
    
    //循环添加“-”
    for (int i = 0; i < spaceCount; i++) {
        if (i == 0) {
            [tempStr insertString:@" " atIndex:3];
        }else if (i == 1) {
            [tempStr insertString:@" " atIndex:8];
        }
    }
    return tempStr;
}

// 判断字符串是否手机号
- (BOOL)jj_isPhoneNumber
{
    NSString *regex = @"^[1][3-9]\\d{9}$";
    NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
    if ([regextestmobile evaluateWithObject:self] == NO) {
        return NO;
    }
    return YES;
}

// 判断字符串是否email
- (BOOL)jj_isEmail
{
    NSString * email = @"^[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$";
    NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", email];
    if ([regextestmobile evaluateWithObject:self] == NO)
        return NO;
    return YES;
}

// 校正手机号：如去掉前面的86，17951等，并且只取11位
- (NSString *)jj_adjustedPhoneNumber
{
    NSString *phoneNum = [self stringByReplacingOccurrencesOfString:@" " withString:@""];
    phoneNum = [phoneNum stringByReplacingOccurrencesOfString:@"+" withString:@""];
    phoneNum = [phoneNum stringByReplacingOccurrencesOfString:@"-" withString:@""];
    
    {
        phoneNum = [phoneNum stringByReplacingOccurrencesOfString:@" (" withString:@""];
        phoneNum = [phoneNum stringByReplacingOccurrencesOfString:@") " withString:@""];
    }
    
    if ([phoneNum hasPrefix:@"86"]) {
        phoneNum = [phoneNum substringFromIndex:2];
    }
    if ([phoneNum hasPrefix:@"17951"]) {
        phoneNum = [phoneNum substringFromIndex:5];
    }
    if (phoneNum.length > 11)
        return [phoneNum substringWithRange:NSMakeRange(0, 11)];
    return phoneNum;
}


+ (NSString *)jj_updateRequestInfo:(NSArray *)arr
{
    NSString *requestData = [NSString jj_dictionaryToJson:arr];
    
    requestData = [requestData stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    requestData = [requestData stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    requestData = [requestData stringByReplacingOccurrencesOfString:@" " withString:@""];
    return requestData;
}

+ (NSString *)jj_dictionaryToJson:(id)obj
{
    NSError *parseError = nil;
    NSData  *jsonData = [NSJSONSerialization dataWithJSONObject:obj options:NSJSONWritingPrettyPrinted error:&parseError];
    NSString *requestData = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    requestData = [requestData stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    requestData = [requestData stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    requestData = [requestData stringByReplacingOccurrencesOfString:@" " withString:@""];
    return requestData;
}

- (NSString *)jj_numFromString {
    // Intermediate
    NSMutableString *numberString = [[NSMutableString alloc] init];
    NSString *tempStr;
    NSScanner *scanner = [NSScanner scannerWithString:self];
    NSCharacterSet *numbers = [NSCharacterSet characterSetWithCharactersInString:@"0123456789."];
    
    while (![scanner isAtEnd]) {
        // Throw away characters before the first number.
        [scanner scanUpToCharactersFromSet:numbers intoString:NULL];
        
        // Collect numbers.
        [scanner scanCharactersFromSet:numbers intoString:&tempStr];
        [numberString appendString:tempStr];
        tempStr = @"";
    }
    // Result.
    return numberString;
}

#pragma mark - JSONString、NSDictionary、NSArray
+ (NSString *)jj_dictionaryToJSONString:(NSDictionary *)dictionary {
    NSError *error = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:NSJSONWritingPrettyPrinted error:&error];
    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    return jsonString;
}

+ (NSDictionary *)jj_dictionaryFromJSONString:(NSString *)jsonString {
    if (jsonString == nil) {
        return nil;
    }
    NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
    NSError *err;
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&err];
    if(err) {
        NSLog(@"json解析失败：%@",err);
        return nil;
    }
    return dic;
}

+ (NSString *)jj_arrayToJSONString:(NSArray *)array {
    NSError *error = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:array options:NSJSONWritingPrettyPrinted error:&error];
    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    return jsonString;
}

+ (NSArray *)jj_arrayFromJSONString:(NSString *)jsonString {
    if (jsonString == nil) {
        return nil;
    }
    NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
    NSError *err;
    NSArray *arr = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&err];
    if(err) {
        NSLog(@"json解析失败：%@",err);
        return nil;
    }
    return arr;
}

@end
